﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

using LowLevelGraphics;
using ImageRecognition2.CustomControls;

namespace ImageRecognition2.Forms
{
    public partial class FormGraduationCurves : Form
    {
        Bitmap srcBmp, distBmp;
        float zoom = 1.0f;
        Channel channel;

        public FormGraduationCurves()
        {
            InitializeComponent();
            this.Shown += new EventHandler(FormGraduationCurves_Shown);
            this.graduationCurves1.LevelChangedEvent += new LevelChangedEventHandler(this.imageCurve1_LevelChangedEvent);
        }

        void FormGraduationCurves_Shown(object sender, EventArgs e)
        {
            imagePanel1.Image = srcBmp = (Bitmap)MainFormSingleton.ActivePictureBox.BackgroundImage;            
        }

        private void imageCurve1_LevelChangedEvent(object sender, LevelChangedEventArgs e)
        {
            distBmp = ChangeChannelLevel(srcBmp, imagePanel1.SelectedArea, channel, e.LevelValue);            
            imagePanel1.Image = distBmp;
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            channel = (Channel)cobChannel.SelectedIndex;
        }

        public static Bitmap ChangeChannelLevel(Bitmap image, Rectangle selectedArea, Channel channel, byte[] Levels)
        {
            Rectangle selectRect;
            if (selectedArea == new Rectangle(0, 0, 0, 0))
                selectRect = new Rectangle(1, 1, image.Width - 2, image.Height - 2);
            else
                selectRect = selectedArea;

            Bitmap bmp = (Bitmap)image.Clone();

            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);

            UnsafeBitmap bitmap = bmp;
            BitmapData bmpData = bitmap.BitmapData;

            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            int bytes = bmpData.Stride * bmp.Height;
            byte[] rgbValues = new byte[bytes];
            int bytesStart = bitmap.BytesPerPixelCount * selectRect.Left - 1;
            int bytesEnd = bitmap.BytesPerPixelCount * selectRect.Right + 1;
            int scanStart = selectRect.Top * bmpData.Stride;
            int scanEnd = selectRect.Bottom * bmpData.Stride;

            if (channel == Channel.All)
            {
                // Copy the RGB values into the array.
                Marshal.Copy(ptr, rgbValues, 0, bytes);

                // I try use for... for... two loops, but it is much slower 
                // than one loop

                for (int i = scanStart; i < scanEnd + 1; i++)//only one loop 
                {
                    int w = i % bmpData.Stride;
                    if (w > bytesStart && w < bytesEnd)
                    {
                        rgbValues[i] = Levels[rgbValues[i]];
                    }
                }
            }
            else
            {
                int integer = (int)channel;

                // Copy the RGB values into the array.
                Marshal.Copy(ptr, rgbValues, 0, bytes);

                for (int i = scanStart; i < scanEnd + 1; i++) //only one loop 
                {
                    int w = i % bmpData.Stride;
                    int p = w % bitmap.BytesPerPixelCount;
                    if (w > bytesStart && w < bytesEnd && p == integer)
                    {
                        rgbValues[i] = Levels[rgbValues[i]];
                    }
                }
            }

            // Copy the RGB values back to the bitmap
            Marshal.Copy(rgbValues, 0, ptr, bytes);

            // Unlock the bits.
            bmp.UnlockBits(bmpData);

            return bmp;
        }

        private void cbOK_Click(object sender, EventArgs e)
        {

        }

        private void cbCancel_Click(object sender, EventArgs e)
        {

        }

        private void cbAuto_Click(object sender, EventArgs e)
        {

        }
    }
}

